/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { TaskHandler } from './task/TaskHandler';
import { BitmapSize } from './bitmap/core/BitmapSize';
import { Downloader } from './bitmap/download/Downloader';
import { TextUtils } from './util/TextUtils'
import { BitmapDisplayConfig } from './bitmap/BitmapDisplayConfig'
import { BitmapGlobalConfig } from './bitmap/BitmapGlobalConfig'
import { BitmapLoadCallBack } from './bitmap/callback/BitmapLoadCallBack';
import { DefaultBitmapLoadCallBack } from './bitmap/callback/DefaultBitmapLoadCallBack'
import { BitmapLoadTask } from './task/BitmapLoadTask';
import { BitmapCacheListener } from './bitmap/BitmapCacheListener'
import { Context } from '@ohos.abilityAccessCtrl';

export class BitmapUtils implements TaskHandler {
  pauseTask = false;
  pauseTaskLock: object | null = null;
  context: Context | null = null;
  globalConfig: BitmapGlobalConfig;
  defaultDisplayConfig: BitmapDisplayConfig;
  size: BitmapSize | null = null
  textUtils: TextUtils;
  requestMsg: string[] = [];
  private cancelAllTask = false;

  constructor(context?: ESObject, diskCachePath ?: string, memoryCachePercent?: number, diskCacheSize?: number) {
    this.context = context;
    this.globalConfig = diskCachePath == undefined ? new BitmapGlobalConfig('') : new BitmapGlobalConfig(diskCachePath);
    this.defaultDisplayConfig = new BitmapDisplayConfig();
    this.globalConfig.setDiskCacheSize(diskCacheSize);
    this.textUtils = new TextUtils();

  }
  //////////////////////////////////////// config ////////////////////////////////////////////////////////////////////

  configDefaultLoadingImage(res: Resource, pix: PixelMap): BitmapUtils {
    if (res != null) {
      this.defaultDisplayConfig.setLoadingDrawable(res);
    } else if (pix != null) {
      this.defaultDisplayConfig.setLoadingPixMap(pix)
    }
    return this;
  }

  public configDefaultLoadFailedImage(res: Resource ,pix: PixelMap): BitmapUtils {
    if (res != null) {
      this.defaultDisplayConfig.setLoadFailedDrawable(res);
    } else if (pix != null) {
      this.defaultDisplayConfig.setLoadFailedPixelMap(pix);
    }
    return this;
  }

  public configDefaultAutoRotation(autoRotation: boolean): BitmapUtils {
    this.defaultDisplayConfig.setAutoRotation(autoRotation);
    return this;
  }

  public configDefaultShowOriginal(showOriginal: boolean): BitmapUtils {
    this.defaultDisplayConfig.setShowOriginal(showOriginal);
    return this;
  }

  public configDefaultDisplayConfig(displayConfig: BitmapDisplayConfig): BitmapUtils {
    this.defaultDisplayConfig = displayConfig;
    return this;
  }

  public configDownloader(downloader: Downloader): BitmapUtils {
    this.globalConfig.setDownloader(downloader);
    return this;
  }

  public configDefaultCacheExpiry(defaultExpiry: number): BitmapUtils {
    this.globalConfig.setDefaultCacheExpiry(defaultExpiry);
    return this;
  }

  public configDefaultConnectTimeout(connectTimeout: number): BitmapUtils {
    this.globalConfig.setDefaultConnectTimeout(connectTimeout);
    return this;
  }

  public configDefaultReadTimeout(readTimeout: number): BitmapUtils {
    this.globalConfig.setDefaultReadTimeout(readTimeout);
    return this;
  }

  public configMemoryCacheEnabled(enabled: boolean): BitmapUtils {
    this.globalConfig.setMemoryCacheEnabled(enabled);
    return this;
  }

  setImageSize(val1?: number, val2?: number, val3?: BitmapSize) {
    if (typeof val1 == 'number' && val1 >= 0 && typeof val2 == 'number' && val2 >= 0) {
      this.size = new BitmapSize(val1, val2);
    } else if (val3 == null && val3 != null) {
      this.size = val3;
    }
  }

  public configBitmapCacheListener(listener?: BitmapCacheListener): BitmapUtils {
    this.globalConfig.setBitmapCacheListener(listener);
    return this;
  }

  ////////////////////////// display ////////////////////////////////////
  display(uri: string, displayConfig?: BitmapDisplayConfig, callBack?: BitmapLoadCallBack) {
    if (callBack == null) {
      callBack = new DefaultBitmapLoadCallBack();
    }
    if (displayConfig == null || displayConfig == this.defaultDisplayConfig) {
      displayConfig = this.defaultDisplayConfig.cloneNew();
    }

    displayConfig.setBitmapMaxSize(this.size);
    if (this.requestMsg.indexOf(uri) == -1) {
      this.requestMsg.push(uri);
    }

    //从缓存中读取图片
    this.globalConfig.getBitmapCache().getBitmapFromMemCache(uri, (bitmap) => {
      if (bitmap != null) {
        callBack?.onLoadMemoryCompleted(uri, bitmap);
      } else if (this.requestMsg.length > 0) {
        for (let index = this.requestMsg.length; index > 0; index--) {
          let loadTask = new BitmapLoadTask(this.requestMsg[this.requestMsg.length-1],  displayConfig as ESObject, callBack, this.globalConfig);
          loadTask.executeOnExecutorForPixelMap();
          this.requestMsg.pop()
        }
      }
    });
  }

  clearCache(fileName?: string) {
    this.globalConfig.clearCache(fileName);
  }

  clearMemoryCache(fileName?: string) {
    this.globalConfig.clearMemoryCache(fileName);
  }

  flushCache() {
    this.globalConfig.flushCache();
  }

  closeCache() {
    this.globalConfig.closeCache();
  }

  getBitmapFileFromDiskCache(url: string): string {
    return this.globalConfig.getBitmapCache().getBitmapFileFromDiskCache(url);
  }

  supportPause(): boolean {
    return true;
  }

  supportResume(): boolean {
    return true;
  }

  supportCancel(): boolean {
    return true;
  }

  pause() {
    this.pauseTask = true;
    this.flushCache();
  }

  resume() {
    this.pauseTask = false;
    this.pauseTaskLock = null;

  }

  cancel() {
    this.pauseTask = true;
    this.cancelAllTask = true;
    this.pauseTaskLock = null;
  }

  isPaused(): boolean {
    return this.pauseTask;
  }

  public isCancelled(): boolean {
    return this.cancelAllTask;
  }
}

